package me.minetsh.imaging.view.stick;

import me.minetsh.imaging.ResourceTable;
import ohos.agp.components.*;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * IMGStickerView
 *
 * @since 2021-07-27
 */
public class IMGStickerView extends ComponentContainer implements Component.DrawTask,
        Component.EstimateSizeListener, ComponentContainer.ArrangeListener, Component.TouchEventListener {
    private Component mContentView;

    private float mScale = 1f;

    private static final int ANCHOR_SIZE = 48;

    private static final int ANCHOR_SIZE_HALF = ANCHOR_SIZE >> 1;

    private static int mBaseTextSize = 70;

    private static final int PADDING = 30;

    private static final float STROKE_WIDTH = 3;

    private Image mRemoveView, mAdjustView;

    private IMGStickerMoveHelper mMoveHelper;

    private Matrix mMatrix = new Matrix();

    private RectFloat mFrame = new RectFloat();

    private Text mTextView;

    private Paint mPaint;

    private IMGStickerPortrait imgStickerPortrait;

    private boolean isShowBorder = true;

    /**
     * 构造函数
     *
     * @param context 上下文
     */
    public IMGStickerView(Context context) {
        super(context);
        onInitialize(context);
    }

    /**
     * 构造函数
     *
     * @param context 上下文
     * @param attrSet 属性
     */
    public IMGStickerView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        onInitialize(context);
    }

    /**
     * 构造函数
     *
     * @param context   上下文
     * @param attrSet   属性
     * @param styleName 样式名
     */
    public IMGStickerView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        onInitialize(context);
    }

    /**
     * 设置文字贴片接口
     *
     * @param imgStickerPortrait 文字贴片接口
     */
    public void setIMGStickerPortrait(IMGStickerPortrait imgStickerPortrait) {
        this.imgStickerPortrait = imgStickerPortrait;
    }

    private void onInitialize(Context context) {
        mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.STROKE_STYLE);
        mPaint.setStrokeWidth(STROKE_WIDTH);

        mContentView = onCreateContentView(context);
        addComponent(mContentView, getContentLayoutParams());

        mRemoveView = new Image(context);
        mRemoveView.setScaleMode(Image.ScaleMode.ZOOM_CENTER);
        mRemoveView.setPixelMap(ResourceTable.Media_image_ic_delete);
        addComponent(mRemoveView, getAnchorLayoutParams());
        mRemoveView.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                removeTextView();
            }
        });

        mAdjustView = new Image(context);
        mAdjustView.setScaleMode(Image.ScaleMode.ZOOM_CENTER);
        mAdjustView.setPixelMap(ResourceTable.Media_image_ic_adjust);
        addComponent(mAdjustView, getAnchorLayoutParams());

        new IMGStickerAdjustHelper(this, mAdjustView);

        mMoveHelper = new IMGStickerMoveHelper(this);
        setEstimateSizeListener(this::onEstimateSize);
        setArrangeListener(this::onArrange);
        addDrawTask(this::onDraw);
        setTouchEventListener(this::onTouchEvent);
    }

    /**
     * 添加缩放数值
     *
     * @param scale 缩放数值
     */
    public void addScaleValue(float scale) {
        setScaleValue(getScaleValue() * scale);
    }

    /**
     * 获取缩放数值
     *
     * @return 缩放数值
     */
    public float getScaleValue() {
        return mScale;
    }

    /**
     * 设置缩放数值
     *
     * @param scale 缩放数值
     */
    public void setScaleValue(float scale) {
        mScale = scale > 3.5f ? 3.5f : scale;
        mScale = mScale < 1f ? 1f : mScale;

        mContentView.setScaleX(mScale);
        mContentView.setScaleY(mScale);

        int pivotX = (getLeft() + getRight()) >> 1;
        int pivotY = (getTop() + getBottom()) >> 1;

        mFrame.fuse(pivotX, pivotY, pivotX, pivotY);
        mFrame.fuse(-(mContentView.getWidth() >> 1), -(mContentView.getHeight() >> 1));

        mMatrix.setScale(mScale, mScale);
        mMatrix.mapRect(mFrame);
        invalidate();
        postLayout();
    }

    private Component onCreateContentView(Context context) {
        mTextView = new Text(context);
        mTextView.setTextSize(mBaseTextSize);
        mTextView.setPadding(PADDING, PADDING, PADDING, PADDING);
        mTextView.setTextColor(Color.WHITE);
        mTextView.setMultipleLine(true);
        return mTextView;
    }

    private LayoutConfig getContentLayoutParams() {
        return new LayoutConfig(LayoutConfig.MATCH_CONTENT, LayoutConfig.MATCH_CONTENT);
    }

    private LayoutConfig getAnchorLayoutParams() {
        return new LayoutConfig(ANCHOR_SIZE, ANCHOR_SIZE);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (isShowBorder) {
            canvas.drawRect(ANCHOR_SIZE_HALF, ANCHOR_SIZE_HALF,
                    getWidth() - ANCHOR_SIZE_HALF,
                    getHeight() - ANCHOR_SIZE_HALF, mPaint);
        }
    }

    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        int count = getChildCount();
        int maxHeight = 0;
        int maxWidth = 0;

        for (int i = 0; i < count; i++) {
            final Component child = getComponentAt(i);
            if (child.getVisibility() != Component.INVISIBLE) {
                child.estimateSize(widthMeasureSpec, heightMeasureSpec);
                maxWidth = Math.round(Math.max(maxWidth, child.getEstimatedWidth() * child.getScaleX()));
                maxHeight = Math.round(Math.max(maxHeight, child.getEstimatedHeight() * child.getScaleY()));

            }
        }
        setEstimatedSize(maxWidth, maxHeight);

        return true;
    }

    @Override
    public boolean onArrange(int left, int top, int right, int bottom) {
        mFrame.fuse(left, top, right, bottom);

        int count = getChildCount();
        if (count == 0) {
            return false;
        }

        mRemoveView.arrange(0, 0, mRemoveView.getWidth(), mRemoveView.getHeight());
        mAdjustView.arrange(
                right - left - mAdjustView.getWidth(),
                bottom - top - mAdjustView.getHeight(),
                mAdjustView.getWidth(), mAdjustView.getHeight()
        );

        int centerX = (right - left) >> 1;
        int centerY = (bottom - top) >> 1;
        int hw = mContentView.getEstimatedWidth() >> 1;
        int hh = mContentView.getEstimatedHeight() >> 1;
        mContentView.arrange(centerX - hw, centerY - hh, mContentView.getEstimatedWidth(), mContentView.getEstimatedHeight());

        return true;
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        return mMoveHelper.onTouch(this, event);
    }

    /**
     * 设置文字贴片
     *
     * @param text  文字
     * @param color 颜色
     */
    public void setStickerText(String text, Color color) {
        mTextView.setText(text);
        mTextView.setTextColor(color);
        invalidate();
        postLayout();
    }

    /**
     * 获取文字贴片文字
     *
     * @return 文字
     */
    public String getStickerText() {
        return mTextView.getText();
    }

    /**
     * 获取文字贴片颜色
     *
     * @return 颜色值
     */
    public Color getStickerTextColor() {
        return mTextView.getTextColor();
    }

    /**
     * 获取视图
     *
     * @return 视图
     */
    public Component getContentView() {
        return mContentView;
    }

    /**
     * 删除文字贴片
     */
    public void removeTextView() {
        if (imgStickerPortrait != null) {
            imgStickerPortrait.remove(this);
        }
    }

    /**
     * 显示边框
     */
    public void showBorder() {
        if (!isShowBorder) {
            isShowBorder = true;
            mRemoveView.setVisibility(VISIBLE);
            mAdjustView.setVisibility(VISIBLE);
            invalidate();
        }
    }

    /**
     * 隐藏边框
     */
    public void disMissBorder() {
        if (isShowBorder) {
            isShowBorder = false;
            mRemoveView.setVisibility(INVISIBLE);
            mAdjustView.setVisibility(INVISIBLE);
            invalidate();
        }
    }

    /**
     * 设置是否可点击
     *
     * @param canTouch 是否可点击
     */
    public void setCanTouch(boolean canTouch) {
        if (canTouch) {
            this.setTouchEventListener(this::onTouchEvent);
        } else {
            this.setTouchEventListener(null);
        }
    }
}
